<html>
<head><meta charset="utf-8"><title>Lifetimes and the stack · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html">Lifetimes and the stack</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="214675584"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214675584" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Ahmed Charles <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214675584">(Oct 27 2020 at 09:18)</a>:</h4>
<p>Is it possible to make the following work?</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">enum</span> <span class="nc">Node</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">Empty</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">Cons</span><span class="p">(</span><span class="kt">u32</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;'</span><span class="na">a</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">Node</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="p">),</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">recurse</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="p">(</span><span class="n">d</span>: <span class="kt">u32</span><span class="p">,</span><span class="w"> </span><span class="n">n</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="na">a</span> <span class="nc">mut</span><span class="w"> </span><span class="n">Node</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"hi {}"</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"bye {}"</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="k">return</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Node</span>::<span class="n">Cons</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">);</span><span class="w"></span>

<span class="w">    </span><span class="n">recurse</span><span class="p">(</span><span class="n">d</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">list</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"bye {}"</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">node</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Node</span>::<span class="n">Empty</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Node</span>::<span class="n">Cons</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">node</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="n">recurse</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">list</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="214676280"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214676280" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214676280">(Oct 27 2020 at 09:25)</a>:</h4>
<p>You can remove all the <code>mut</code>s:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">enum</span> <span class="nc">Node</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">Empty</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">Cons</span><span class="p">(</span><span class="kt">u32</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;'</span><span class="na">a</span><span class="w"> </span><span class="n">Node</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="p">),</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">recurse</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="p">(</span><span class="n">d</span>: <span class="kt">u32</span><span class="p">,</span><span class="w"> </span><span class="n">n</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="na">a</span> <span class="nc">Node</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"hi {}"</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"bye {}"</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="k">return</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Node</span>::<span class="n">Cons</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">);</span><span class="w"></span>

<span class="w">    </span><span class="n">recurse</span><span class="p">(</span><span class="n">d</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">list</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"bye {}"</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">node</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Node</span>::<span class="n">Empty</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Node</span>::<span class="n">Cons</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">node</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="n">recurse</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">list</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>

<p>since this makes <code>Node</code> covariant</p>



<a name="214676322"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214676322" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214676322">(Oct 27 2020 at 09:25)</a>:</h4>
<p>using <code>mut</code> your example does not work because <code>let mut list = Node::Cons(1, n);</code> means that <code>list</code> does not live for <code>'a</code></p>



<a name="214677384"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214677384" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214677384">(Oct 27 2020 at 09:37)</a>:</h4>
<p>Here's a version that compiles, using <a href="https://crates.io/crates/typed-arena"><code>typed-arena</code></a>:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">use</span><span class="w"> </span><span class="n">typed_arena</span>::<span class="n">Arena</span><span class="p">;</span><span class="w"></span>

<span class="k">enum</span> <span class="nc">Node</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">Empty</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">Cons</span><span class="p">(</span><span class="kt">u32</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;'</span><span class="na">a</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">Node</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="p">),</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">recurse</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="p">(</span><span class="n">arena</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="na">a</span> <span class="nc">Arena</span><span class="o">&lt;</span><span class="n">Node</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;&gt;</span><span class="p">,</span><span class="w"> </span><span class="n">d</span>: <span class="kt">u32</span><span class="p">,</span><span class="w"> </span><span class="n">n</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="na">a</span> <span class="nc">mut</span><span class="w"> </span><span class="n">Node</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"hi {}"</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"bye {}"</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="k">return</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arena</span><span class="p">.</span><span class="n">alloc</span><span class="p">(</span><span class="n">Node</span>::<span class="n">Cons</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">));</span><span class="w"></span>

<span class="w">    </span><span class="n">recurse</span><span class="p">(</span><span class="n">arena</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">list</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"bye {}"</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">arena</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Arena</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">node</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Node</span>::<span class="n">Empty</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arena</span><span class="p">.</span><span class="n">alloc</span><span class="p">(</span><span class="n">Node</span>::<span class="n">Cons</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">node</span><span class="p">));</span><span class="w"></span>
<span class="w">    </span><span class="n">recurse</span><span class="p">(</span><span class="o">&amp;</span><span class="n">arena</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">list</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="214682518"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214682518" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Ahmed Charles <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214682518">(Oct 27 2020 at 10:35)</a>:</h4>
<p><span class="user-mention silent" data-user-id="216206">lcnr</span> <a href="#narrow/stream/122651-general/topic/Lifetimes.20and.20the.20stack/near/214676322">said</a>:</p>
<blockquote>
<p>using <code>mut</code> your example does not work because <code>let mut list = Node::Cons(1, n);</code> means that <code>list</code> does not live for <code>'a</code></p>
</blockquote>
<p>Why is that?</p>



<a name="214694493"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214694493" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214694493">(Oct 27 2020 at 12:53)</a>:</h4>
<p>so recurse expects <code>n</code> to be a mutable reference with lt <code>'a</code> to a <code>Node</code> which contains an <code>'a</code>. These two <code>'a</code> have to be the same</p>



<a name="214694617"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214694617" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214694617">(Oct 27 2020 at 12:55)</a>:</h4>
<p>as you however create the <code>list</code> on the stack is has only lives for some <code>'0</code></p>



<a name="214694637"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214694637" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214694637">(Oct 27 2020 at 12:55)</a>:</h4>
<p>this <code>'0</code> is not equal to <code>'a</code> however, as <code>'a</code> comes from outside of the function</p>



<a name="214694731"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214694731" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214694731">(Oct 27 2020 at 12:56)</a>:</h4>
<p>so you then try to call <code>recurse</code> with <code>&amp;'0 mut Node&lt;'a&gt;</code> which is results in an error as <code>'0 != 'a</code></p>



<a name="214746222"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214746222" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Ahmed Charles <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214746222">(Oct 27 2020 at 18:48)</a>:</h4>
<p>Ok, though I guess it just seems weird that it works for shared references, since those would have a similar issue?</p>



<a name="214747598"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214747598" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Joshua Nelson <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214747598">(Oct 27 2020 at 18:59)</a>:</h4>
<p>I think it has something to do with variance?</p>



<a name="214747650"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214747650" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Joshua Nelson <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214747650">(Oct 27 2020 at 18:59)</a>:</h4>
<p>personally I never really understood that section <a href="https://doc.rust-lang.org/nomicon/subtyping.html#variance">https://doc.rust-lang.org/nomicon/subtyping.html#variance</a></p>



<a name="214748961"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214748961" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214748961">(Oct 27 2020 at 19:08)</a>:</h4>
<p>It's not too hard to see why the original version is actually unsound: the variable <code>n</code> in <code>recurse</code> refers to a bunch of nodes up the stack, so you could traverse down the list, replace a node in the middle with something in the current stack frame, and then when you exit the scope this gets dropped and your node has a dangling reference in it</p>



<a name="214749452"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214749452" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214749452">(Oct 27 2020 at 19:11)</a>:</h4>
<p>For shared references, you have read-only access, so it's safe to shrink the lifetime, but when you have mutable references a shorter lifetime means you can also put shorter lifetime things in the reference</p>



<a name="214750353"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214750353" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214750353">(Oct 27 2020 at 19:19)</a>:</h4>
<p>^ what <span class="user-mention silent" data-user-id="271719">Mario Carneiro</span> said.</p>
<p>it is fine to shrink the lifetime of immutable references, so you can use <code>&amp;'static T</code> where <code>&amp;'a T</code> is expected.<br>
For mutable references this is however not possible, as you could otherwise do the following: <code>&amp;'static mut T -&gt; &amp;'a mut T</code>,  replace <code>T</code> with a <code>T</code> which only lives for <code>'a</code>. When you now access the original <code>&amp;'static mut T</code> afterwards you access freed memory</p>



<a name="214761736"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214761736" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214761736">(Oct 27 2020 at 20:44)</a>:</h4>
<p>I think <code>&amp;'static mut T -&gt; &amp;'a mut T</code> is fine by variance, but <code>&amp;'static mut T&lt;'static&gt; -&gt; &amp;'a mut T&lt;'a&gt;</code> is not</p>



<a name="214761775"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214761775" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214761775">(Oct 27 2020 at 20:45)</a>:</h4>
<p><code>&amp;'a mut T</code> is covariant in <code>'a</code> but invariant in <code>T</code></p>



<a name="214762207"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214762207" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214762207">(Oct 27 2020 at 20:48)</a>:</h4>
<p>so where that gets in trouble is having a double reference, like <code>&amp;mut &amp;mut T</code>, and you try to change what the caller's reference is pointing to</p>



<a name="214770169"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214770169" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214770169">(Oct 27 2020 at 22:02)</a>:</h4>
<p><span class="user-mention silent" data-user-id="232545">Joshua Nelson</span> <a href="#narrow/stream/122651-general/topic/Lifetimes.20and.20the.20stack/near/214747650">said</a>:</p>
<blockquote>
<p>personally I never really understood that section <a href="https://doc.rust-lang.org/nomicon/subtyping.html#variance">https://doc.rust-lang.org/nomicon/subtyping.html#variance</a></p>
</blockquote>
<p>I've written several posts on URLO to try and "teach" that notion, feel free to tell me which one is the most useful one to you:</p>
<ul>
<li>Shortest one: <a href="https://users.rust-lang.org/t/totally-confused-by-the-rule-of-lifetime-and-variance/36984/5">https://users.rust-lang.org/t/totally-confused-by-the-rule-of-lifetime-and-variance/36984/5</a></li>
<li>A bit longer: <a href="https://users.rust-lang.org/t/refcell-confuses-the-compiler-well-mostly-me/46078/3">https://users.rust-lang.org/t/refcell-confuses-the-compiler-well-mostly-me/46078/3</a></li>
<li>A counter-example: <a href="https://users.rust-lang.org/t/what-a-phantom-do/36655/11">https://users.rust-lang.org/t/what-a-phantom-do/36655/11</a></li>
<li>Another explanation, more contravariance focused: <a href="https://users.rust-lang.org/t/function-with-a-generic-type-as-a-callback/34867/6">https://users.rust-lang.org/t/function-with-a-generic-type-as-a-callback/34867/6</a></li>
<li>And the main one: <code>PhantomData</code> usages, including variance: <a href="https://users.rust-lang.org/t/looking-for-a-deeper-understanding-of-phantomdata/32477/4">https://users.rust-lang.org/t/looking-for-a-deeper-understanding-of-phantomdata/32477/4</a></li>
</ul>
<hr>
<p>The super TL,DR, being that:</p>
<ul>
<li>covariance represents the capacity to shrink the lifetime parameters inside a generic type (and contravariance is the "inverse", the capacity of growing it, which basically only happens if the lifetime parameter was appearing as the input parameter of a function).</li>
</ul>
<p>And the practical rules that follow, which are surprisingly simple:</p>
<ul>
<li>
<p>When in doubt, be invariant: this conservative choice is always sound;</p>
</li>
<li>
<p>If something is immutable, then it can be covariant. "That's why" type <code>f&lt;X&gt; = &amp;'_ X</code> is covariant.</p>
</li>
<li>
<p>If the thing is owned, then covariance is fine too, even if immutability is no longer guaranteed (<code>X</code>, <code>Box&lt;X&gt;</code>, <code>ARc&lt;X&gt;</code>, etc.).</p>
</li>
<li>
<p>When something is mutable but not owned (such as <code>&amp;'_ mut X</code>), then it is invariant (covariance would be unsound).</p>
</li>
<li>
<p>This leads to the awkward situation of the shared mutability wrappers, such as <code>UnsafeCell</code>, <code>Cell</code>, <code>RefCell</code>, <code>Mutex</code>, <code>RwLock</code>. These, by value, are owned, so covariance would be fine.</p>
<p>But if they were covariant and <code>&amp;'_ X</code> was covariant too, by composition <code>&amp;'_ Cell&lt;X&gt;</code>, etc. would be covariant too, which is unsound, since these are mutable non-owning types.</p>
<p>So the choice was made that mutability wrappers be invariant, even when owned.</p>
</li>
</ul>



<a name="214774162"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214774162" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214774162">(Oct 27 2020 at 22:44)</a>:</h4>
<p>Without reading through all these, is there any reason this elaboration shouldn't be partially "upstreamed" into the nomicon?</p>



<a name="214799523"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Lifetimes%20and%20the%20stack/near/214799523" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Ahmed Charles <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Lifetimes.20and.20the.20stack.html#214799523">(Oct 28 2020 at 06:21)</a>:</h4>
<p>Thanks, this makes sense.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>